/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package hxg.portmgr.core.device;

import hxg.portmgr.core.ip.IpAddress;
import hxg.portmgr.core.ip.IpAddressEntry;
import hxg.portmgr.core.ip.IpSubnet;
import java.util.*;
import java.util.logging.Logger;
import hxg.portmgr.core.dao.DaoSource;
import hxg.portmgr.core.device.intf.Intf;
import hxg.portmgr.core.device.intf.IntfState;
import hxg.portmgr.core.oper.OperType;
import hxg.portmgr.core.oper.snmp.SnmpOper;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Map.Entry;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;

/**
 *
 * @author hxg
 */
public class DeviceUtils {

    private static final Logger logger = Logger.getLogger(DeviceUtils.class.getName());

    public static TreeMap<DeviceType, TreeMap<DeviceModel, TreeSet<Device>>> getDeviceTree(Collection<Device> devs) {
        TreeMap<DeviceType, TreeMap<DeviceModel, TreeSet<Device>>> mp = new TreeMap();
        for (Device dev : devs) {
            TreeMap<DeviceModel, TreeSet<Device>> mmp;
            if (mp.containsKey(dev.getType())) {
                mmp = mp.get(dev.getType());
                if (!mmp.containsKey(dev.getModel())) {
                    mmp.put(dev.getModel(), new TreeSet<Device>());
                }
                mmp.get(dev.getModel()).add(dev);
                //mmp.put(dev.getModel(), set);
            } else {
                mmp = new TreeMap();
                TreeSet<Device> set = new TreeSet();
                set.add(dev);
                mmp.put(dev.getModel(), set);
            }
            mp.put(dev.getType(), mmp);
        }
        return mp;
    }

    public static void submitScanDevice(Collection<Device> devs) {
        for (Device dev : devs) {
            for (IpAddressEntry ip : dev.ips) {
                if (!IpAddress.isSiteLocalAddress(ip.getIp())) {
                    DaoSource.getDeviceDao().addDevice(dev);
                }
            }
        }
    }

    public static Map<IpSubnet, Collection<Device>> getDeviceIpMap() {
        Map<IpSubnet, Collection<Device>> mp = new LinkedHashMap<>();
        for (Device dev : DaoSource.getDeviceDao().getDevices()) {
            for (IpAddressEntry ipEntry : dev.getIps()) {
                IpSubnet subnet = ipEntry.getIpAddr().getIpSubnet();
                if (!mp.containsKey(subnet)) {
                    mp.put(subnet, new HashSet<Device>());
                }
                mp.get(subnet).add(dev);
            }
        }
        return mp;
    }

    public static void getIntfStates(Collection<Device> devs, final boolean autoOpenAdminDownIntf) throws IOException {
        final File openIntffile = new File(".\\exp\\DeviceUtils\\IntfState\\打开纪录.txt");
        if (!openIntffile.getParentFile().exists()) {
            openIntffile.getParentFile().mkdirs();
        }
        final BufferedWriter openpw = new BufferedWriter(new FileWriter(openIntffile, false));
        ExecutorService service = Executors.newFixedThreadPool(8);
        List<Future> furs = new ArrayList<>();
        for (final Device dev : devs) {
            final SnmpOper oper = (SnmpOper) dev.getOper(OperType.SnmpOper);
            final AtomicInteger atomint = new AtomicInteger(0);                //try {
            final File f = new File(".\\exp\\DeviceUtils\\IntfState\\" + dev.getModel() + "_" + dev.getIp() + "_" + dev.getChsName() + ".txt");
            f.getParentFile().mkdirs();
            Future<Integer> fur = service.submit(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    try (BufferedWriter wr = new BufferedWriter(new FileWriter(f, false))) {
                        Intf[] infs = dev.getIntfs();
                        Map<Intf, IntfState[]> mp = oper.getIntfState(infs);
                        for (Intf inf : infs) {
                            IntfState[] states = mp.get(inf);
                            wr.append(dev.getIp()).append(',');
                            wr.append(dev.getChsName()).append(',');
                            wr.append(inf.getMarkName()).append(',');
                            wr.append(states[0].toString()).append(',');
                            wr.append(states[1].toString());
                            wr.newLine();
                        }
                        if (autoOpenAdminDownIntf) {
                            for (Entry<Intf, IntfState[]> entry : mp.entrySet()) {
                                IntfState[] states = entry.getValue();
                                if (states[0] == IntfState.AdminDown) {
                                    Intf inf = entry.getKey();
                                    oper.TurnOnPort(inf.getIndex());
                                    IntfState newstate = oper.getIntfState(inf.getIndex());
                                    System.out.println("尝试打开关闭的端口:"+dev.getIp()+"-"+dev.getChsName()+"-"+inf.getMarkName());
                                    openpw.append(dev.getIp()).append(',');
                                    openpw.append(dev.getChsName()).append(',');
                                    openpw.append(inf.getMarkName()).append(',');
                                    openpw.append(states[0].toString()).append(',');
                                    openpw.append(newstate.toString());
                                    openpw.newLine();
                                }
                            }
                        }
                    } catch (IOException ex) {
                        Logger.getLogger(DeviceUtils.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    return atomint.getAndIncrement();
                }
            });
            furs.add(fur);
        }
        service.shutdown();
        for (Future f : furs) {
            try {
                f.get();
            } catch (InterruptedException | ExecutionException ex) {
                Logger.getLogger(DeviceUtils.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        openpw.close();
    }
}
